package net.helix.ui.panels.library;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;

import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;

import net.helix.engine.Engine;
import net.helix.engine.library.LibraryTreeNode;
import net.helix.fileChooser.ImageFilter;
import net.helix.ui.UIImages;
import net.helix.ui.panels.JImageButton;

import org.jdesktop.swingx.JXTreeTable;
import org.lwjgl.LWJGLException;



public class LibraryPane extends JPanel {
	private static final long serialVersionUID = 1L;
	
	JPanel pane1;
	JPanel pane2;
	
	private LibraryPreview libraryPreview = null;
	
	private Engine engine;
	
	private JPopupMenu buttonMenu;
	private JImageButton makePopupButton;
	
	private JXTreeTable treeTable;
	private LibraryTreeTableModel treeModel;
	private JScrollPane treeScroll;
	
	private JTextField filterBox;
	
	private JLabel libDesc;
	public LibraryPane(Engine _engine){
		super();
		this.engine = _engine;
		
		this.setLayout(new GridLayout());
		this.setMinimumSize(new Dimension(200, 200));
		
		buttonMenu = new JPopupMenu();
		
		JMenuItem importImage = new JMenuItem("Import image");
		importImage.addMouseListener(new MouseListeners(ButtonType.IMPORT_IMAGE));
		
		buttonMenu.add(importImage);
		
		JMenuItem importSound = new JMenuItem("Import sound");
		importSound.addMouseListener(new MouseListeners(ButtonType.IMPORT_SOUND));
		buttonMenu.add(importSound);
		
		JMenuItem importModel = new JMenuItem("Import model");
		importModel.addMouseListener(new MouseListeners(ButtonType.IMPORT_MODEL));
		buttonMenu.add(importModel);
		
		JMenuItem newFolder = new JMenuItem("New folder");
		newFolder.addMouseListener(new MouseListeners(ButtonType.NEW_FOLDER));
		
		buttonMenu.add(newFolder);
		
		
		buttonMenu.addSeparator();
		
		
		JMenuItem collapseFolders = new JMenuItem("Collapse folders");
		collapseFolders.addMouseListener(new MouseListeners(ButtonType.COLLAPSE));
		buttonMenu.add(collapseFolders);
		
		JMenuItem expandFolders = new JMenuItem("Expand folders");
		expandFolders.addMouseListener(new MouseListeners(ButtonType.EXPAND));
		buttonMenu.add(expandFolders);
		
		
		buttonMenu.addSeparator();
		
		JMenu sortBy = new JMenu("Sort");
		
		sortBy.add("Alphabetical");
		sortBy.add("Alphabetical + Numeric");
		sortBy.add("Type");
		
		buttonMenu.add(sortBy);
		
		
		
		//this.add(buttonMenu);
		
		
		pane1 = new JPanel();
		pane2 = new JPanel();
		
		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pane1, pane2);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(150);
		splitPane.setContinuousLayout(true);
		
		//Provide minimum sizes for the two components in the split pane
		Dimension minimumSize = new Dimension(100, 50);
		pane1.setMinimumSize(minimumSize);
		pane2.setMinimumSize(minimumSize);
		
		pane1.setLayout(new BorderLayout());
		pane2.setLayout(new BorderLayout());
		
		try {
			libraryPreview = new LibraryPreview(engine, this, engine.sharedGL.gd, engine.sharedGL.pf, engine.sharedGL.sd);
			//engine.sharedGL.setDrawable(libraryPreview);
		} catch (LWJGLException e1) {
			e1.printStackTrace();
		}
		this.addHierarchyListener(new HierarchyListener(){
			
			@Override
			public void hierarchyChanged(HierarchyEvent arg0) {
				if(isDisplayable()){
					
					/*
					System.out.println("hierarchyChanged");
					
					pane1.remove(libraryPreview);
					
					try {
						libraryPreview = new LibraryPreview(engine.sharedGL.gd, engine.sharedGL.pf, engine.sharedGL.sd);
						//engine.sharedGL.setDrawable(libraryPreview);
					} catch (LWJGLException e1) {
						e1.printStackTrace();
					}
					pane1.add(libraryPreview, BorderLayout.CENTER);
					*/
				}
				
			}
			
		});
		
		//canvas = new Canvas();
		/*
		canvas.addComponentListener(new ComponentAdapter() {
	           @Override
	           public void componentResized(ComponentEvent e)
	           { canvas.setBounds(0, 0, pane1.getWidth(), pane1.getHeight()); }
	        });
		*/
		JPanel pane2Bottom = new JPanel();
		//pane1.add(pane2Bottom, BorderLayout.PAGE_END);
		pane1.add(libraryPreview, BorderLayout.CENTER);
		
		pane1.setTransferHandler(new LibraryPreviewTransferHandler(libraryPreview));
		
		
		
		pane2Bottom.setLayout(new BorderLayout());
		
		
		libDesc = new JLabel("");
		
		
		pane2Bottom.add(libDesc, BorderLayout.LINE_START);
		
		makePopupButton = new JImageButton(UIImages.popupGeneratorIcon);
		makePopupButton.setPreferredSize(new Dimension(15, 15));
		makePopupButton.setSize(new Dimension(15, 15));
		makePopupButton.setToolTipText("Add...");
		makePopupButton.addMouseListener(new MouseListener(){
			@Override
			public void mouseClicked(MouseEvent e) {
				buttonMenu.show(makePopupButton, 0, makePopupButton.getHeight());
			}
			@Override
			public void mouseEntered(MouseEvent e) {
				
			}
			@Override
			public void mouseExited(MouseEvent e) {
				
			}
			@Override
			public void mousePressed(MouseEvent e) {
				
			}
			@Override
			public void mouseReleased(MouseEvent e) {
				
			}
		});
		
		JPanel popupButtonContainer = new JPanel();
		
		pane2Bottom.add(popupButtonContainer, BorderLayout.LINE_END);
		popupButtonContainer.setLayout(new FlowLayout());
		popupButtonContainer.add(makePopupButton);
		
		treeModel = new LibraryTreeTableModel(engine.getCurrentSelectedLibrary());
		
		treeTable = new JXTreeTable(treeModel);
		
		//treeModel.setTreeTable(treeTable);
		
		treeTable.setColumnControlVisible(true);
		treeTable.setHorizontalScrollEnabled(true);
		
		//treeTable.setEditable(true);
		//treeTable.setShowsRootHandles(false);
		
		
		//treeTable.getColumnModel().getColumn(0).setWidth(250);
		/*
		treeTable.getColumnModel().getColumn(1).setWidth(25);
		treeTable.getColumnModel().getColumn(2).setWidth(25);
		treeTable.getColumnModel().getColumn(3).setWidth(25);
		*/
		
		LibraryTreeTransferHandler handler = new LibraryTreeTransferHandler(treeModel);
		treeTable.setTransferHandler(handler);
		treeTable.setDropTarget(new LibraryTreeDropTarget(treeModel, handler));
		treeTable.setDragEnabled(true);
		
		treeTable.addMouseListener(new LibraryTreeTableMouseListener(this));
		treeTable.addKeyListener(new LibraryTreeTableKeyListener(this));
		//treeTable.enableInputMethods(true);
		
		treeScroll = new JScrollPane();
		treeScroll.setViewportView(treeTable);
		
		redrawLibrary();
		//tree.removeAll();
		
		
		
		filterBox = new JTextField();
		filterBox.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent actionEvent) {
				treeModel.setFilter(filterBox.getText());
			}
			
		});
		
		final JCheckBox filterCaps = new JCheckBox("Case");
		filterCaps.setToolTipText("Case sensitive?");
		filterCaps.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent actionEvent) {
				treeModel.setFilterCase(filterCaps.isSelected());
			}
			
		});
		
		JPanel filterPanel = new JPanel(new BorderLayout());
		filterPanel.add(filterBox, BorderLayout.CENTER);
		filterPanel.add(filterCaps, BorderLayout.LINE_END);
		
		pane2.add(treeScroll, BorderLayout.CENTER);
		pane2.add(pane2Bottom, BorderLayout.PAGE_START);
		
		pane2.add(filterPanel, BorderLayout.PAGE_END);
		
		
		this.add(splitPane);
		
		
		
		/*
		try {
			Display.setParent(canvas);
		} catch (LWJGLException e) {
			e.printStackTrace();
		}
   	 	Display.setVSyncEnabled(true);
		*/
		
		
		
	}
	public JPanel getLibraryPreviewParentPanel(){
		return pane1;
	}
	public LibraryPreview getLibraryPreview(){
		return libraryPreview;
	}
	public void changePreviewPicTo(LibraryTreeNode node){
		libraryPreview.changePreviewPicTo(node);
	}
	public void redrawLibrary(){
		System.out.println("redrawLibrary");
		/*
		top.removeAllChildren();
		
		if(engine.getCurrentSelectedLibrary() != null){
			top.setUserObject(engine.getCurrentSelectedLibrary().tree);
		}
		*/
		
		
		if(engine.getCurrentSelectedLibrary() != null){
			
			//TableColumnModel columns = treeTable.getColumnModel();
			
			treeModel.setRoot(engine.getCurrentSelectedLibrary());
			
			System.out.println("columns "+treeTable.getColumnModel().getColumnCount());
			
			// TODO: make these real so they can actually do something
			JPopupMenu popup = new JPopupMenu();
			
			JMenuItem itemRename = new JMenuItem("Rename");
			itemRename.addMouseListener(new MouseAdapter(){
				@Override
				public void mouseReleased(MouseEvent e) {
					System.out.println("Renaming");
					treeTable.editCellAt(treeTable.getSelectedRow(), treeTable.getSelectedColumn(), null);
					// TODO: figure out how to make cell's textfield selected so that the arrow keys left and right don't exit out of editing cell...
					
					treeTable.setEditingRow(treeTable.getSelectedRow());
					treeTable.setEditingColumn(treeTable.getSelectedColumn());
					
					//treeTable.c
					//treeTable.getCellEditor().
				}
			});
			popup.add(itemRename);
			
			//popup.add("Rename");
			
			JMenuItem itemDelete = new JMenuItem("Delete");
			itemDelete.addMouseListener(new DeleteItems());
			
			//popup.add("Delete");
			popup.add(itemDelete);
			
			popup.add("Create copy");
			popup.addSeparator();
			popup.add("Properties");
			
			treeTable.setComponentPopupMenu(popup);
			
			
			// treeTable.getColumnModel().setColumnMargin(2);
			
			if(treeTable.getColumnCount() > 0){
				treeTable.getColumn(0).setWidth(200);
				if(treeTable.getColumnCount() > 1){
					treeTable.getColumn(1).setWidth(40);
					if(treeTable.getColumnCount() > 2){
						treeTable.getColumn(2).setWidth(20);
						if(treeTable.getColumnCount() > 3){
							treeTable.getColumn(3).setWidth(100);
						}
					}
				}
				
				
			}
			
			//treeTable.setColumnModel(columns);
			//treeTable.getColumnModel().getColumn(0).setWidth(250);
			
			/*
			if(treeScroll != null){
				pane2.remove(treeScroll);
			}
			tree = new JTree(engine.getCurrentSelectedLibrary().tree.getTreeNode());
			tree.setRootVisible(false);
			tree.setScrollsOnExpand(true);
			tree.setCellRenderer(new LibraryCellRenderer());
			tree.setCellEditor(new LibraryCellEditor(tree, (DefaultTreeCellRenderer) tree.getCellEditor()));
			tree.setDragEnabled(true);
			tree.setVisibleRowCount(3);
			
			treeScroll = new JScrollPane(tree);
			pane2.add(treeScroll, BorderLayout.CENTER);
			*/
			
			int size = engine.getCurrentSelectedLibrary().getNumberOfItems();
			if(size == 0){
				libDesc.setText("No items");
			}else if(size == 1){
				libDesc.setText("1 items");
			}else{
				libDesc.setText(size + " items");
			}
			
		}else{
			libDesc.setText("No timeline selected");
		}
		//tree.repaint();
		
	}
	public LibraryTreeTableModel getTreeTableModel(){
		return treeModel;
	}
	public JXTreeTable getTreeTable(){
		return treeTable;
	}
	
	class DeleteItems extends MouseAdapter{
		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO: add "are you sure" dialogue
			// treeModel.removeNodeFromParent();
			int rows[] = treeTable.getSelectedRows();
			ArrayList<LibraryTreeNode> nodes = new ArrayList<LibraryTreeNode>(rows.length);
			
			for(int i=0;i<rows.length;i++){
				nodes.add((LibraryTreeNode) treeTable.getPathForRow(rows[i]).getLastPathComponent());
			}
			treeModel.deleteNodes(nodes);
			
			libraryPreview.changePreviewPicTo(null);
			
		}
	}
	
	enum ButtonType{
		IMPORT_IMAGE, IMPORT_SOUND, IMPORT_MODEL, NEW_FOLDER, COLLAPSE, EXPAND
	}
	class MouseListeners extends MouseAdapter implements Runnable{
		ButtonType type;
		public MouseListeners(ButtonType type){
			this.type = type;
		}
		@Override
		public void mouseReleased(MouseEvent e) {
			if(type == ButtonType.IMPORT_IMAGE){
				JFileChooser fileBrowser = new JFileChooser();
				fileBrowser.setName("Import image");
				fileBrowser.setMultiSelectionEnabled(true);
				
				fileBrowser.setAcceptAllFileFilterUsed(true);
				fileBrowser.setFileFilter(fileBrowser.getAcceptAllFileFilter());
				
				fileBrowser.addChoosableFileFilter(new ImageFilter("png", "Portable Network Graphics (*.png)"));
				fileBrowser.addChoosableFileFilter(new ImageFilter("gif", "Graphics Interchange Format (*.gif)"));
				fileBrowser.addChoosableFileFilter(new ImageFilter(new String[]{"jpeg", "jpg", "jpe"}, "JPEG Image (*.jpeg, *.jpg, *.jpe)"));
				// TODO: bitmap, tif, tga
				fileBrowser.addChoosableFileFilter(new ImageFilter(new String[]{"png", "gif", "jpeg", "jpg", "jpe"}, "All supported image files"));
				
				
				//fileBrowser.addChoosableFileFilter(new ImageFilter(new String[]{"tar", "vda", "icb", "vst"}, "TarGA Image (*.tar, *.vda, *.icb, *.vst)"));
				fileBrowser.setApproveButtonText("Import");
				
				if(fileBrowser.showOpenDialog(engine.mainWindow) == JFileChooser.APPROVE_OPTION){
					
					
						
					final File[] files = fileBrowser.getSelectedFiles();
					
					libraryPreview.setRunOnceFunction(
					new Runnable(){

						@Override
						public void run() {
							
							engine.handleImageImport(files, treeModel);
							
						}
						
					});
					libraryPreview.repaint();
					
					
					//redrawLibrary();
				}
				
				
				
				
				
				
			}
			if(type == ButtonType.IMPORT_SOUND){
				JFileChooser fileBrowser = new JFileChooser();
				fileBrowser.setName("Import image");
				fileBrowser.setMultiSelectionEnabled(true);
				
				fileBrowser.setAcceptAllFileFilterUsed(true);
				fileBrowser.setFileFilter(fileBrowser.getAcceptAllFileFilter());
				
				fileBrowser.addChoosableFileFilter(new ImageFilter("wav", "WAV file (*.wav)"));
				
				fileBrowser.setApproveButtonText("Import");
				
				if(fileBrowser.showOpenDialog(engine.mainWindow) == JFileChooser.APPROVE_OPTION){
					File[] files = fileBrowser.getSelectedFiles();
					engine.handleSoundImport(files, treeModel);
					
					//redrawLibrary();
				}
			}
			if(type == ButtonType.IMPORT_MODEL){
				JFileChooser fileBrowser = new JFileChooser();
				fileBrowser.setName("Import model");
				fileBrowser.setMultiSelectionEnabled(true);
				
				fileBrowser.setAcceptAllFileFilterUsed(true);
				fileBrowser.setFileFilter(fileBrowser.getAcceptAllFileFilter());
				
				fileBrowser.addChoosableFileFilter(new ImageFilter("obj", "Wavefront obj file (*.obj)"));
				fileBrowser.addChoosableFileFilter(new ImageFilter("3ds", "3ds file (*.3ds)"));
				
				fileBrowser.addChoosableFileFilter(new ImageFilter(new String[]{"obj", "md3"}, "All supported model files"));
				
				//fileBrowser.addChoosableFileFilter(new ImageFilter(new String[]{"tar", "vda", "icb", "vst"}, "TarGA Image (*.tar, *.vda, *.icb, *.vst)"));
				fileBrowser.setApproveButtonText("Import");
				
				if(fileBrowser.showOpenDialog(engine.mainWindow) == JFileChooser.APPROVE_OPTION){
					
						
					final File[] files = fileBrowser.getSelectedFiles();
					
					libraryPreview.setRunOnceFunction(
					new Runnable(){

						@Override
						public void run() {
							
							engine.handleModelImport(files, treeModel);
							
						}
						
					});
					libraryPreview.repaint();
					
					//redrawLibrary();
				}
				
			}
			if(type == ButtonType.NEW_FOLDER){
				treeModel.addNewFolder();
				
				//engine.addNewFolder();
				//redrawLibrary();
			}
			if(type == ButtonType.COLLAPSE){
				treeTable.collapseAll();
			}
			if(type == ButtonType.EXPAND){
				treeTable.expandAll();
			}
		}
		@Override
		public void run(){
		}
		
		
	}
	
	

}
